<template>
  <div>
    <h2>动态表格demo</h2>
    <div style="text-align: right; margin-bottom: 10px">
      <el-button-group>
        <el-button type="" icon="el-icon-plus" size="mini" @click="addLine"
          >加一行</el-button
        >
        <el-button
          type="danger"
          icon="el-icon-delete"
          size="mini"
          @click="deleteFunc"
          >删除行</el-button
        >
      </el-button-group>
    </div>
    <el-table
      :data="options.tableData"
      :cell-class-name="tableRowClassName"
      @row-click="handleChoose"
      highlight-current-row
      border
      @cell-click="handleCellClick"
    >
      <el-table-column
        v-for="item in options.columns"
        :key="item.prop"
        :prop="item.prop"
        :label="item.label"
        :align="options.align"
        :width="item.width"
      >
        <div v-if="item.columnType == 'enum'" slot-scope="scope">
          <div v-if="scope.row.index === tabClickIndex && item.prop === tabClickProp">
            <el-select
              ref="inputRef"
              v-model="scope.row[item.prop]"
              @visible-change="visibleChange"
              style="width: 100%"
              size="mini"
              :disabled="!item.editFlag"
              automatic-dropdown
              @keydown.tab.native="forbidSelectTab($event)"
            >
              <el-option
                v-for="element in item.optionArr"
                :key="element.value"
                :label="element.label"
                :value="element"
              >
              </el-option>
            </el-select>
          </div>
          <div v-else :style="{ textAlign: options.align }">
            {{ scope.row[item.prop] | changeObj }}
          </div>
        </div>

        <div v-else slot-scope="scope">
          <div v-if="scope.row.index === tabClickIndex && item.prop === tabClickProp">
            <el-input
              ref="inputRef"
              v-model="scope.row[item.prop]"
              size="mini"
              :disabled="!item.editFlag"
              @blur="blurFunc"
              @keyup.enter.native="forbidTab($event)"
              @keydown.tab.native="forbidTab($event)"
              @keydown.up.native="clickUp($event)"
              @keydown.down.native="clickDown($event)"
            ></el-input>
          </div>
          <div v-else :style="{ textAlign: options.align }">
            {{ scope.row[item.prop] }}
          </div>
        </div>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableD: {
        type: "table",
        icon: "el-icon-bank-card",
        name: "动态表格",
        options: {
          tableData: [
            { abcd001: "", abcd002: " ", abcd003: " " },
            { abcd001: "", abcd002: " ", abcd003: " " },
          ],
          align: "center",
          columns: [
            {
              label: "列1",
              prop: "abcd001",
              columnType: "string",
              editFlag: true,
              relateFlag: false,
              computerFlag: false,
            },
            {
              label: "列2",
              prop: "abcd002",
              columnType: "string",
              editFlag: true,
              relateFlag: false,
              computerFlag: false,
            },
            {
              label: "列3",
              prop: "abcd003",
              columnType: "enum",
              editFlag: true,
              relateFlag: false,
              computerFlag: false,
              optionArr: [
                { value: "option01", label: "选项1" },
                { value: "option02", label: "选项2" },
              ],
            },
          ],
        },
      },
      previewFlag: true,
      tabClickIndex: null, // 点击的单元格
      tabClickIndexB: null, // 点击的单元格(备份)，用于tab按键跳转下一格事件 
      tabClickProp: "", // 当前点击的列名
      tabClickPropB: "", // 当前点击的列名(备份)，用于tab按键跳转下一格事件 
      options: {
        tableData: [],
        columns: [],
      },
      columnsValue: {}, // 新增时空的数据内容
      chooseLine: {},   // 获取当前行(用于删除)
    };
  },
  filters: {
    changeObj: function(value) {
      return value ? value.label : '';
    }
  },
  created() {
    this.tableD && (this.options = this.tableD.options);
    this.columnsValue = JSON.parse(JSON.stringify(this.options.tableData[0]));
    for (let key in this.columnsValue) {
      if (key.length > 10) {
        // 用于新增一行时候，所需的表头属性和空value值
        this.columnsValue[key] = "";
      }
    }
  },
  methods: {
    // 快捷键Tab 切换下一格
    forbidTab(e) {
      e.preventDefault();
      console.log("监听到按下Tab...");
      let colLen = this.options.columns.length;
      let rowLen = this.options.tableData.length;

      this.tabClickProp =
        this.tabClickProp === "" ? this.tabClickPropB : this.tabClickProp;

      let currentIndex = this.options.columns.findIndex(value => {
        return value.prop === this.tabClickProp;
      });

      if (currentIndex === colLen - 1) {
        // 最后一列，换行处理
        if (this.tabClickIndex !== rowLen - 1) {
          let indexData01 = this.tabClickIndex + 1; // 预存row index
          // 触发blur
          this.tabClickIndex = null;
          this.tabClickProp = "";
          this.$nextTick(() => {
            this.tabClickProp = this.options.columns[0].prop;
            this.tabClickIndex = indexData01;
            this.$nextTick(() => {
              this.$refs.inputRef[0].focus();
            });
          });
          console.log("最后一列，换行了");
        } else {
          this.tabClickIndex = null;
          this.tabClickProp = "";
          console.log("最后一列，最后一个");
        }
      } else {
        // 不是最后一列，直接到下一格，行号不变  列号加一
        let indexData02 = this.tabClickIndex; // 预存row index
        // 触发blur
        this.tabClickIndex = null;
        this.tabClickProp = "";
        // 重新激活
        this.$nextTick(() => {
          this.tabClickProp = this.options.columns[currentIndex + 1].prop;
          this.tabClickIndex = indexData02;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        });
      }
    },
    // 快捷键Tab 切换下一格（用于select框切换）
    forbidSelectTab(e) {
      e.preventDefault();
      console.log("监听到按下Tab...");
      let colLen = this.options.columns.length;
      let rowLen = this.options.tableData.length;

      let currentIndex = this.options.columns.findIndex(value => (value.prop === this.tabClickPropB))

      if (currentIndex === colLen - 1) {
        // 最后一列，换行处理
        let indexData01 =
          this.tabClickIndex === null
            ? this.tabClickIndexB + 1
            : this.tabClickIndex + 1; // 预存row index
        if (indexData01 !== rowLen) {
          // 触发blur
          this.tabClickIndex = null;
          this.tabClickProp = "";
          this.$nextTick(() => {
            this.tabClickProp = this.options.columns[0].prop;
            this.tabClickIndex = indexData01;

            this.$nextTick(() => {
              this.$refs.inputRef[0].focus();
            });
          });
          console.log("select最后一列，换行了");
        } else {
          this.tabClickIndex = null;
          this.tabClickProp = "";
          console.log("select最后一列，最后一个");
        }
      } else {
        // 不是最后一列，直接到下一格，行号不变  列号加一
        let indexData02 =
          this.tabClickIndex === null
            ? this.tabClickIndexB
            : this.tabClickIndex; // 预存row index
        // 触发blur
        this.tabClickIndex = null;
        this.tabClickProp = "";
        // 重新激活
        setTimeout(() => {
          this.tabClickProp = this.options.columns[currentIndex + 1].prop;
          this.tabClickIndex = indexData02;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        }, 160);
      }
    },
    // 快捷键'上(UP)'
    clickUp(e) {
      e.preventDefault();
      console.log("监听到按下UP...");
      let oldIndex = this.tabClickIndex;
      let oldkProp = this.tabClickProp;
      let lastIndex = this.options.tableData.length - 1;
      this.blurFunc();
      if (oldIndex !== 0) {
        this.$nextTick(() => {
          this.tabClickIndex = oldIndex - 1;
          this.tabClickProp = oldkProp;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        });
      } else {
        this.$nextTick(() => {
          this.tabClickIndex = lastIndex;
          this.tabClickProp = oldkProp;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        });
        console.log("到顶啦！");
        return false;
      }
    },
    // 快捷键'下(Down)'
    clickDown(e) {
      e.preventDefault();
      console.log("监听到按下Down...");
      let oldIndex = this.tabClickIndex;
      let oldkProp = this.tabClickProp;
      let lastIndex = this.options.tableData.length - 1;
      this.blurFunc();
      if (oldIndex < lastIndex) {
        this.$nextTick(() => {
          this.tabClickIndex = oldIndex + 1;
          this.tabClickProp = oldkProp;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        });
      } else {
        this.$nextTick(() => {
          this.tabClickIndex = 0;
          this.tabClickProp = oldkProp;
          this.$nextTick(() => {
            this.$refs.inputRef[0].focus();
          });
        });
        console.log("到底啦！");
        return false;
      }
    },

    handleCellClick(row, column) {
      // 获取当前table中的 行、列标识
      this.tabClickIndex = row.index;
      this.tabClickProp = column.property;
      // 备份处理
      this.tabClickIndexB = this.tabClickIndex;
      this.tabClickPropB = this.tabClickProp;

      this.$nextTick(() => {
        this.$refs.inputRef[0].focus();
      });
    },
    blurTimeFunc() {
      // 日期选择器失去焦点
      this.tabClickIndexB = this.tabClickIndex;
      this.tabClickPropB = this.tabClickProp;

      this.tabClickIndex = null;
      this.tabClickProp = "";
    },
    blurFunc() {
      this.tabClickIndex = null;
      this.tabClickProp = "";
    },
    visibleChange(value) {
      // select 失去下拉后调用
      this.tabClickIndexB = this.tabClickIndex;
      this.tabClickPropB = this.tabClickProp;

      if (value === false) {
        this.tabClickIndex = null;
        this.tabClickProp = "";
      }
    },
    tableRowClassName({ row, column, rowIndex, columnIndex }) {
      //把每一行的索引放进row,和index
      row.index = rowIndex;
      column.index = columnIndex;
    },

    handleChoose(row) {
      this.chooseLine = row;
    },
    addLine() {
      // 加一行
      this.options.tableData.push(
        JSON.parse(JSON.stringify(this.columnsValue))
      );
      let tabLen = this.options.tableData.length;
      // 聚焦新行，第一格
      this.tabClickProp = this.options.columns[0].prop;
      this.tabClickIndex = tabLen - 1;
      this.$nextTick(() => {
        this.$refs.inputRef[0].focus();
      });
    },
    deleteFunc() {
      if (JSON.stringify(this.chooseLine) !== "{}") {
        let index = this.chooseLine.index;
        this.$confirm(
          "当前操作将删除第 " + (index + 1) + " 行, 是否继续?",
          "提示",
          {
            confirmButtonText: "确 定",
            cancelButtonText: "取 消",
            type: "warning",
          }
        )
          .then(() => {
            // 调用删除接口
            this.options.tableData.splice(index, 1);
            this.$message.success("操作成功");
            this.chooseLine = {};
          })
          .catch(() => {
            return false;
          });
      } else {
        this.$message.error("未选择删除行");
      }
    },
  },
};
</script>